package utils

import (
	"context"
	"encoding/json"
	"gin_study_blog/common"
	"gin_study_blog/models"
	"gin_study_blog/service/redis"
	"github.com/olivere/elastic/v7"
	"strings"
)

type Option struct {
	models.PageInfo
	Fields []string
	Tags   string
}

func (a Option) getFrom() int {
	if a.Limit == 0 {
		a.Limit = 10
	}
	if a.Page == 0 {
		a.Page = 10
	}
	return (a.Page - 1) * a.Limit
}

// CommList 封装公用 es 查询
func CommList(option Option) (list []models.ArticleModel, count int, err error) {
	// 创建一个新的布尔查询
	boolSearch := elastic.NewBoolQuery()
	if option.Key != "" {
		// Must方法表示这个匹配查询是必需的，也就是说只有当这个匹配查询返回结果时，布尔查询才会返回结果。
		boolSearch.Must(
			// NewMatchQuery 必须完全匹配 NewFuzzyQuery 模糊匹配 NewMultiMatchQuery 多个搜索字段
			elastic.NewMultiMatchQuery(option.Key, option.Fields...),
		)
	}

	if option.Tags != "" {
		// Must方法表示这个匹配查询是必需的，也就是说只有当这个匹配查询返回结果时，布尔查询才会返回结果。
		boolSearch.Must(
			// NewMatchQuery 必须完全匹配 NewFuzzyQuery 模糊匹配 NewMultiMatchQuery 多个搜索字段
			elastic.NewMultiMatchQuery(option.Tags, "tags"),
		)
	}

	type sortFiled struct {
		Filed     string
		Ascending bool
	}

	sortFiledData := sortFiled{
		Filed:     "created_at",
		Ascending: false, // false 正序 // true 倒叙
	}
	if option.Sort != "" {
		_list := strings.Split(option.Sort, " ")
		if len(_list) == 2 && (_list[1] == "desc" || _list[1] == "asc") {
			sortFiledData.Filed = _list[0]
			if _list[1] == "desc" {
				sortFiledData.Ascending = false
			}
			if _list[1] == "asc" {
				sortFiledData.Ascending = true
			}
		}
	}

	res, err := common.EsClient.Search(models.ArticleModel{}.Index()).
		Query(boolSearch).
		Highlight(elastic.NewHighlight().Field("title")).
		From(option.getFrom()).
		Sort(sortFiledData.Filed, sortFiledData.Ascending).
		Size(option.Limit).Do(context.Background())
	if err != nil {
		return list, 0, err
	}
	// 搜索的结果数
	count = int(res.Hits.TotalHits.Value)
	articleList := []models.ArticleModel{}

	diggInfo := redis.NewDigg().GetInfoAll()
	lookInfo := redis.NewArticleLook().GetInfoAll()
	commentInfo := redis.NewCommentCount().GetInfoAll()
	for _, hit := range res.Hits.Hits {
		var model models.ArticleModel
		err = json.Unmarshal(hit.Source, &model)
		if err != nil {
			common.Log.Error(err.Error())
			continue
		}
		// 替换高亮
		title, ok := hit.Highlight["title"]
		if ok {
			model.Title = title[0]
		}
		model.ID = hit.Id
		digg := diggInfo[hit.Id]
		model.LikeCount = model.LikeCount + digg

		look := lookInfo[hit.Id]
		model.LookCount = model.LookCount + look

		comment := commentInfo[hit.Id]
		model.CommentCount = model.CommentCount + comment
		articleList = append(articleList, model)
	}
	return articleList, count, nil
}

// CommDetail 根据 id获取 es文章详情
func CommDetail(id string) (detail models.ArticleModel, err error) {
	res, err := common.EsClient.Get().Index(models.ArticleModel{}.Index()).Id(id).Do(context.Background())
	if err != nil {
		common.Log.Error(err.Error())
		return
	}
	err = json.Unmarshal(res.Source, &detail)
	if err != nil {
		common.Log.Error(err.Error())
		return
	}
	detail.ID = res.Id
	detail.LookCount = detail.LookCount + redis.NewArticleLook().Get(res.Id)
	return
}
